<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://d3js.org/d3.v5.min.js"></script>
</head>

<body>
  <div id="app">

  </div>
  <hr>
  <button id="btn-update">update</button>
  <script>
    var svg_width = 600;
    var svg_height = 450;
    var padding = 30;
    var colors = d3.schemeCategory10;

    //生成画布
    var svg = d3.select('#app').append('svg').attr("width", svg_width).attr("height", svg_height)
      .style("background", '#efefef')


    var dataset = [];
    function MockData() {
      dataset = [];
      for (let i = 0; i < 30; i++) {
        let x = Math.ceil(Math.random() * 14000);
        let y = Math.ceil(Math.random() * 14000);
        dataset.push({ x, y })
      }
    }


    //添加散点
    function addCircle() {
      svg.append('g')
        .attr('class', 'grop_circle')
        .attr('clip-path', 'url(#rect-clip-path)')
        .selectAll('circle')
        .data(dataset)
        .enter()
        .append('circle')
        .attr('r', 10)
        .attr('cx',  (d, i)=> {
          return this.xScale(d.x);
        })
        .attr('cy', (d, i)=> {
          return this.yScale(d.y);
        })
        .attr('fill', (d, i) => colors[i % 10])
    }


    //添加坐标轴
    function addAxis() {
      this.xScale = d3.scaleLinear().domain([0, d3.max(dataset, (d) => d.x)]).range([padding, svg_width - padding]);

      //x方向坐标轴
      this.xAxis = d3.axisBottom(this.xScale)

      svg.append('g')
        .attr('id', 'x_axis')
        .call(this.xAxis)
        .attr("transform", `translate(0,${svg_height - padding})`)

      //y方向的坐标轴
      this.yScale = d3.scaleLinear().domain([0, d3.max(dataset, (d) => {
        return d.y;
      })]).range([svg_height - padding, padding]);
      this.yAxis = d3.axisLeft(this.yScale);
      svg.append('g')
        .attr('id', 'y_axis')
        .call(this.yAxis)
        .attr("transform", `translate(${padding},0)`)

    }

    function addClipPath() {
      svg.append('clipPath')
        .attr("id", "rect-clip-path")
        .append('rect')
        .attr('x', padding)
        .attr('y', padding)
        .attr('width', svg_width - padding * 2)
        .attr('height', svg_height - padding * 2)
    }

    MockData();
    addAxis();
    addCircle();
    addClipPath();

    d3.select("#btn-update").on('click', () => {
      MockData();
      this.xScale.domain([0, d3.max(dataset, (d) => d.x)]);
      this.yScale.domain([0, d3.max(dataset, (d) => d.y)]);
      this.xAxis = d3.axisBottom(this.xScale);
      this.yAxis = d3.axisLeft(this.yScale);

      svg.select('#x_axis')
        .transition()
        .duration(1000)
        .call(this.xAxis)

      svg.select('#y_axis')
        .transition()
        .duration(1000)
        .call(this.yAxis)


      svg.select('.grop_circle').selectAll('circle')
      .data(dataset)
      .transition()
      .duration(2000)
      .attr('cx',(d,i)=>{
        return this.xScale(d.x)
      })
      .attr('cy',(d,i)=>{
        return this.yScale(d.y);
      })




    })


  </script>


</body>

</html>